from datetime import datetime 
from microblog.app import db
from werkzeug.security import generate_password_hash, check_password_hash 
from flask_login import UserMixin
from microblog.app import login
from sqlalchemy import and_

class Follow(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    followed_id = db.Column(db.Integer, index=True)
    follower_id = db.Column(db.Integer, index=True)

    def __repr__(self):
        return f'<followed_id {self.followed_id} follower_id {self.follower_id}>'

class User(UserMixin, db.Model):
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(64), index=True, unique=True)
    email = db.Column(db.String(120), index=True, unique=True)
    password_hash = db.Column(db.String(128))
    #posts = db.relationship('Post', backref='author', lazy='dynamic')
    about_me = db.Column(db.String(140))
    last_seen = db.Column(db.DateTime, default=datetime.utcnow)

    def set_password(self, password):
        self.password_hash = generate_password_hash(password)

    def check_password(self, password):
        return check_password_hash(self.password_hash, password)

    def posts(self):
        return Post.query.filter_by(user_id=self.id)

    def followed(self):
        return User.query.join(Follow, Follow.followed_id == User.id).filter(Follow.follower_id == self.id)

    def follower(self):
        return User.query.join(Follow, Follow.follower_id == User.id).filter(Follow.followed_id == self.id)

    def is_following(self, user_id):
        return User.query.join(
            Follow, Follow.followed_id == User.id).filter(
            and_(Follow.follower_id == self.id, Follow.followed_id == user_id)).count() > 0

    def follow(self, user_id):
        if not self.is_following(user_id):
            f = Follow(followed_id=user_id, follower_id=self.id)
            db.session.add(f)

    def unfollow(self, user_id):
        if self.is_following(user_id):
            f = Follow.query.filter(Follow.follower_id == self.id and Follow.followed_id == user_id).first()
            db.session.delete(f)

    def followed_posts(self):
        followed = Post.query.join(Follow, Follow.followed_id == Post.user_id).filter(
            Follow.follower_id == self.id)
        own = Post.query.filter_by(user_id=self.id)
        return followed.union(own).order_by(Post.timestamp.desc())


    def __repr__(self):
        return f'<User> {self.username}'

@login.user_loader
def load_user(id):
    return User.query.get(int(id))

class Post(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    body = db.Column(db.String(140))
    timestamp = db.Column(db.DateTime, index=True, default=datetime.utcnow())
    #user_id = db.Column(db.Integer, db.ForeignKey('user.id'))
    user_id = db.Column(db.Integer, index=True)

    def author(self):
        return User.query.filter_by(id=self.user_id).first()

    def __repr__(self):
        return f'<Post {self.body} user_id {self.user_id} Author {self.author()}>'



